package com.example.yk2021xm04.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.yk2021xm04.exceptions.ParamsException;
import com.example.yk2021xm04.mapper.ProjectMapper;
import com.example.yk2021xm04.pojo.Project;
import com.example.yk2021xm04.pojo.ProjectUser;
import com.example.yk2021xm04.pojo.User;
import com.example.yk2021xm04.query.ProjectQuery;
import com.example.yk2021xm04.service.IProjectService;
import com.example.yk2021xm04.service.IProjectUserService;
import com.example.yk2021xm04.service.IUserService;
import com.example.yk2021xm04.utils.AssertUtil;
import com.example.yk2021xm04.utils.PageResultUtil;
import org.apache.commons.lang3.StringUtils;
import org.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ZengQi
 * @since 2021-11-26
 */
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {

    @Resource
    private IProjectUserService projectUserService;

    @Resource
    private IUserService userService;

    @Autowired
    private StringEncryptor stringEncryptor;

    /**
     * 查询登录用户参加的项目
     * 查看的是私有项目
     * 实现分页
     * @author ZengQi
     * @date 2021/12/11 0011 22:33
     * @param projectQuery
     * @return Map<Object>
     */
    @Override
    public Map<String, Object> projectList(ProjectQuery projectQuery) {
        //查询用户参与的project项目
//        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//        User user = (User) principal;
        final User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        System.out.println(user);
        Integer userId = user.getId();
        System.out.println("第几页："+projectQuery.getPage()+"一页多少数据:"+projectQuery.getLimit());
        Page<Project> page = new Page<>(projectQuery.getPage(), projectQuery.getLimit());
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();

        if(!(user.getRoleNames().contains("超级管理员"))) {
            queryWrapper.eq("u.id",userId);
//            queryWrapper.eq("p.is_private", 1);
        }
        //这里就是代表 sql语句中的 like
        if(StringUtils.isNotBlank(projectQuery.getProjectName())) {
            queryWrapper.like("p.project_name",projectQuery.getProjectName());
        }
        System.out.println(projectQuery.getProjectName());
        IPage<Project> queryProjectPage = this.baseMapper.findProjectByPage(page,userId,queryWrapper);
        System.out.println("一共多少个项目数据:"+queryProjectPage.getTotal()+"本次查询的项目数据量："+queryProjectPage.getRecords().size());

        List<Project> projectList = queryProjectPage.getRecords();

        for(Project p : projectList) {
            p.setProjectLeader(projectUserService.findProjectLeaderByCreateId(p.getCreateId()));
        }

        return PageResultUtil.getResult(queryProjectPage.getTotal(), queryProjectPage.getRecords());
    }

    /**
     *
     * @author ZengQi
     * @date 2021/12/14 0014 14:20
     * @param ids
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteProject(Integer[] ids) {
        final User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        System.out.println(user);
        Integer userId = user.getId();

        AssertUtil.isTrue(null==ids || ids.length==0,"请选择待删除的id");
        List<Project> projectList = this.baseMapper.selectList(new QueryWrapper<Project>().in("id",Arrays.asList(ids)));
        for(Project p : projectList) {
            // 如果该项目是他创建的，则删除
            if(Objects.equals(p.getCreateId(), userId)) {
                AssertUtil.isTrue(!(projectUserService.remove(new QueryWrapper<ProjectUser>().eq("project_id",p.getId()))),
                        "您所创建的"+p.getProjectName()+"项目用户信息删除失败");
                AssertUtil.isTrue(!(this.removeById(p.getId())),"您所创建的"+p.getProjectName()+"项目删除失败");
            } else {
                throw new ParamsException("您不是该项目的创建者，无权删除该项目!");
            }
        }
//        int count = projectUserService.count(new QueryWrapper<ProjectUser>().in("project_id",Arrays.asList(ids)));
//        if (count > 0) {
//            AssertUtil.isTrue(!(projectUserService.remove(new QueryWrapper<ProjectUser>().in("project_id",Arrays.asList(ids)))),
//                    "项目信息删除失败");
//        }
//        AssertUtil.isTrue(!(this.removeByIds(Arrays.asList(ids))),"项目删除失败");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void addProject(Project project) {
        /**
         * 1. 项目名
         * 非空 不可重复
         * 2. 项目经理
         * 存在
         * 3. 项目描述
         * 非空
         * 4. 项目开始时间和结束时间
         * 非空
         * 5. 项目进度默认为0
         * 6. 项目默认私有、有效
         * 7. 成员与项目id进行关联
         */
        AssertUtil.isTrue(StringUtils.isBlank(project.getProjectName()), "项目名不可为空");
        AssertUtil.isTrue(null!=this.findProjectByProjectName(project.getProjectName()),"项目名已存在");
        AssertUtil.isTrue(StringUtils.isBlank(project.getProjectDesc()), "项目描述不可为空");
        System.out.println(project.getBeginTime().toString());
        System.out.println(project.getEndTime().toString());
        AssertUtil.isTrue(StringUtils.isBlank(project.getBeginTime().toString()),"项目开始时间不可为空");

        AssertUtil.isTrue(StringUtils.isBlank(project.getEndTime().toString()),"项目结束时间不可为空");

        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = (User) principal;

        System.out.println(user);
        project.setIsPrivate(true);
        project.setIsDel(false);
        project.setSchedule(0.0);
        project.setCreateId(user.getId());
        project.setProjectLeader(user.getTrueName());
        project.setCreateTime(LocalDateTime.now());
        AssertUtil.isTrue(!(this.save(project)),"项目记录添加失败");

        System.out.println(project.getId());
        //插入一条用户项目信息记录
        relationUserProject(user.getId(), project.getId());
    }

    /**
     * 插入一条用户与项目的关联记录
     * @author ZengQi
     * @date 2021/12/14 0014 15:06
     * @param userId
     * @param projectId
     */
    private void relationUserProject(Integer userId, Integer projectId) {
        int count = projectUserService.count(new QueryWrapper<ProjectUser>().eq("project_id",projectId));
        ProjectUser projectUser = new ProjectUser();
        projectUser.setUserId(userId);
        projectUser.setProjectId(projectId);
        // 如果项目已存在
        if(count > 0) {
            //如果该用户已经加入了该项目
            List<ProjectUser> projectUserList = projectUserService.list(new QueryWrapper<ProjectUser>().eq("user_id",userId));
            List<Integer> projectIds = projectUserList.stream().map(ProjectUser::getProjectId).collect(Collectors.toList());
            AssertUtil.isTrue(projectIds.contains(projectId),"该用户已加入该项目");
        }
        AssertUtil.isTrue(!(projectUserService.save(projectUser)),"项目用户记录添加失败");
    }

    /**
     * 删除一条用户与项目的关联记录
     * @author ZengQi
     * @date 2021/12/14 0014 17:10
     * @param userId
     * @param projectId
     */
    private void removeUserProject(Integer userId, Integer projectId) {
        AssertUtil.isTrue(!(projectUserService.remove(new QueryWrapper<ProjectUser>().eq("user_id",userId).eq("project_id",projectId))),"项目用户记录删除失败");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateProject(Project project) {
        /**
         * 1. 项目名
         * 非空 不可重复
         * 2. 项目描述
         * 非空
         * 3. 项目开始时间和结束时间
         * 非空
         * 5. 只有是该项目的创建者才能更新该项目
         */
        AssertUtil.isTrue(StringUtils.isBlank(project.getProjectName()),"项目名不能为空");
        AssertUtil.isTrue(StringUtils.isBlank(project.getProjectDesc()),"项目描述不能为空");
        AssertUtil.isTrue(StringUtils.isBlank(project.getBeginTime().toString()),"项目开始时间不可为空");
        AssertUtil.isTrue(StringUtils.isBlank(project.getEndTime().toString()),"项目结束时间不可为空");

        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = (User) principal;
        System.out.println(user);
//        AssertUtil.isTrue(null==user,"该项目经理不存在");
        Project temp = this.findProjectByProjectName(project.getProjectName());
        AssertUtil.isTrue(null!=temp&&!(temp.getId().equals(project.getId())),"项目名已存在！");
        if(Objects.equals(temp.getCreateId(), user.getId())) {
            AssertUtil.isTrue(!(this.updateById(project)), "项目更新失败");
        } else {
            throw new ParamsException("您不是该项目的创建者，无法更新该项目");
        }
        //relationUserProject(user.getId(), project.getId());
    }

    @Override
    public IPage<Project> findProjectByPage(IPage<Project> page, Integer userId, QueryWrapper<Project> wrapper) {
        return this.baseMapper.findProjectByPage(page, userId, wrapper);
    }

    @Override
    public void quitProject(Integer id) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = (User) principal;
        System.out.println(user);
        Integer userId = user.getId();
        System.out.println("退出用户id："+userId+"退出项目id："+id);
        removeUserProject(userId,id);
    }

    @Override
    public void joinProject(String inviteUrl) {
        System.out.println(inviteUrl);
        String inviteInfo = "";
        try {
            //处理链接，得到加密信息
            inviteInfo = inviteUrl.substring(36);
            System.out.println(inviteInfo);
            inviteInfo = stringEncryptor.decrypt(inviteInfo);
        } catch (Exception e) {
            throw new ParamsException("无效链接！");
        }
        System.out.println("解密后的信息："+inviteInfo);

        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = (User) principal;
        System.out.println(user);
        //匹配提取inviteCode和inviteCodeCreateTime
        String pattern = "inviteCode=(\\d+)&inviteCodeCreateTime=([\\s\\S]*)";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(inviteInfo);
        String inviteCode = null;
        String inviteCodeCreateTime = null;
        if(m.find()) {
            inviteCode = m.group(1);
            inviteCodeCreateTime = m.group(2);
            System.out.println(m.group(1));
            System.out.println(m.group(2));
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        assert inviteCodeCreateTime != null;
        inviteCodeCreateTime = inviteCodeCreateTime.replace("T"," ");
        LocalDateTime create_time = LocalDateTime.parse(inviteCodeCreateTime,df);
        LocalDateTime current_time = LocalDateTime.now().withNano(0);
        Duration duration = Duration.between(current_time, create_time);
        long hours = duration.toHours();
        if(hours >= 1) {
            throw new ParamsException("邀请链接已超时！");
        }
        relationUserProject(user.getId(), Integer.parseInt(inviteCode));
    }

    @Override
    public List<Object> createTimeByDay() {
        return this.baseMapper.createTimeByDay();
    }

    @Override
    public List<Object> createCountByDay() {
        return this.baseMapper.createCountByDay();
    }

    @Override
    public Integer ProjectCountInDay() {
        return this.baseMapper.ProjectCountInDay();
    }

    private Project findProjectByProjectName(String projectName) {
        return this.baseMapper.selectOne(new QueryWrapper<Project>().eq("project_name",projectName));
    }

    /**
     * 通过项目经理名字查找用户ID
     * @author ZengQi
     * @date 2021/12/8 0008 14:11
     * @param projectLeader
     * @return Integer
     */
    private User findUserByProjectLeader(String projectLeader) {
        return userService.findUserByProjectLeader(projectLeader);
    }
}
